package librarydemo;

import java.io.File;
import java.io.FileWriter;
import java.time.LocalDate;
import java.util.*;

/** 图书馆: 完成“借/还/续 + 异常 + 文件存储(CSV)”等要求 */
public class Library {

    // [出彩-常量] 统一借期参数，方便演示与修改
    public static final int DEFAULT_LOAN_DAYS  = 14;
    public static final int DEFAULT_RENEW_DAYS = 7;

    private final Map<String, Book>   books  = new LinkedHashMap<>();
    private final Map<String, Reader> readers= new LinkedHashMap<>();
    private final Map<String, Loan>   loans  = new LinkedHashMap<>();

    /** 借阅记录：完成“核心类设计（借阅记录）”要求 */
    public static class Loan {
        public final String loanId;
        public final String bookId;
        public final String readerId;
        public final LocalDate borrowDate;
        public LocalDate dueDate;
        public LocalDate returnDate; // 未归还为 null

        public Loan(String loanId, String bookId, String readerId,
                    LocalDate borrowDate, LocalDate dueDate) {
            this.loanId = loanId;
            this.bookId = bookId;
            this.readerId = readerId;
            this.borrowDate = borrowDate;
            this.dueDate = dueDate;
        }

        @Override
        public String toString() {
            return String.format(
                "Loan{loanId='%s', bookId='%s', readerId='%s', borrow=%s, due=%s, returned=%s}",
                loanId, bookId, readerId, borrowDate, dueDate, returnDate);
        }
    }

    // ==== 基础操作 ====
    public void addBook(Book b)            { books.put(b.getId(), b); }
    public void registerReader(Reader r)   { readers.put(r.getId(), r); }
    public Collection<Book>   listBooks()  { return books.values(); }
    public Collection<Reader> listReaders(){ return readers.values(); }
    public Collection<Loan>   listLoans()  { return loans.values(); }

    // 当前未归还数量
    private long countActiveLoans(String readerId) {
        return loans.values().stream()
                .filter(l -> l.readerId.equals(readerId) && l.returnDate == null)
                .count();
    }

    /** [要求-借书方法] 含异常校验 + 写CSV（文件存储） */
    public Loan borrow(String bookId, String readerId, int loanDays) {
        Book b = books.get(bookId);
        Reader r = readers.get(readerId);

        if (b == null) throw new IllegalArgumentException("书不存在：" + bookId);
        if (r == null) throw new IllegalArgumentException("读者不存在：" + readerId);
        if (b.isBorrowed()) throw new IllegalStateException("该书已借出：" + bookId);

        long active = countActiveLoans(readerId);
        if (active >= r.getMaxLoans()) {
            // [要求-异常处理] 使用自定义异常更直观
            throw new BorrowLimitExceededException("超过借书上限（" + r.getMaxLoans() + "）");
        }

        String loanId = "L" + (loans.size() + 1);
        LocalDate now = LocalDate.now();
        Loan loan = new Loan(loanId, bookId, readerId, now, now.plusDays(loanDays));
        loans.put(loanId, loan);
        b.setBorrowed(true);

        appendLoanToCsv("BORROW", loan); // [要求-文件存储] 记录到 CSV
        return loan;
    }

    /** [要求-还书方法] 含异常校验 + 写CSV（文件存储） */
    public void returnBook(String loanId) {
        Loan l = loans.get(loanId);
        if (l == null) throw new IllegalArgumentException("借阅单不存在：" + loanId);
        if (l.returnDate != null) throw new IllegalStateException("已归还，无需重复操作");

        l.returnDate = LocalDate.now();
        Book b = books.get(l.bookId);
        if (b != null) b.setBorrowed(false);

        appendLoanToCsv("RETURN", l); // [要求-文件存储]
    }

    /** [要求-续借方法] 适度校验 + 写CSV（文件存储） */
    public Loan renew(String loanId, int extraDays) {
        Loan l = loans.get(loanId);
        if (l == null) throw new IllegalArgumentException("借阅单不存在：" + loanId);
        if (l.returnDate != null) throw new IllegalStateException("已归还，不可续借");
        l.dueDate = l.dueDate.plusDays(extraDays);

        appendLoanToCsv("RENEW", l); // [要求-文件存储]
        return l;
    }

    // ===== 文件存储: 以 CSV 形式追加写入（项目根目录下 loans.csv） =====
    private static final String CSV_PATH = "loans.csv";

    /** [要求-文件存储] 统一把借/续/还写入 CSV。简单易懂，不引入复杂库。 */
    private void appendLoanToCsv(String action, Loan l) {
        try {
            boolean needHeader = false;
            File f = new File(CSV_PATH);
            if (!f.exists()) needHeader = true;

            try (FileWriter fw = new FileWriter(f, true)) {
                if (needHeader) {
                    fw.write("action,loanId,bookId,readerId,borrowDate,dueDate,returnDate\n");
                }
                String row = String.join(",",
                        action,
                        l.loanId,
                        l.bookId,
                        l.readerId,
                        String.valueOf(l.borrowDate),
                        String.valueOf(l.dueDate),
                        String.valueOf(l.returnDate)) + System.lineSeparator();
                fw.write(row);
            }
        } catch (Exception e) {
            System.out.println("写入CSV失败: " + e.getMessage());
        }
    }
}
